﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using Model01.Logic;

namespace MapOutput
{
    public class Deconvertor
    {
        /// <summary>
        /// Deserialize instance of Map from file fileName.
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private static Map Load(string fileName)
        {
            Map map = null;
            FileStream fs = new FileStream(fileName, FileMode.Open);
            try
            {
                BinaryFormatter formatter = new BinaryFormatter();
                map = (Map)formatter.Deserialize(fs);
            }
            catch (SerializationException e)
            {
                MessageBox.Show("Ошибка десериализации: " + e.Message);
            }
            finally
            {
                fs.Close();
            }
            return map;
        }

        /// <summary>
        /// Get point of the map and return color free if 0 else busy.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="free"></param>
        /// <param name="busy"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private static Color GetMapPoint(Map map, Color free, Color busy, int x, int y)
        {
            if (map[x, y] == 0)
                return free;
            else
                return busy;
        }

        /// <summary>
        /// Deconvert Map to bitmap. Color free - color of free place, color busy - of busy place.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="free"></param>
        /// <param name="busy"></param>
        /// <returns></returns>
        private static Bitmap DeconvertBitmap(Map map, Color free, Color busy)
        {
            Bitmap bitmap = new Bitmap(map.Size.Width, map.Size.Height);
            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
            try
            {
                unsafe
                {
                    byte* pixels = (byte*)bitmapData.Scan0.ToPointer();
                    for (int y = 0; y < bitmapData.Height; y++)
                    {
                        for (int x = 0; x < bitmapData.Width * 3; x += 3)
                        {
                            Color current = GetMapPoint(map, free, busy, x / 3, y);
                            pixels[x] = current.R;
                            pixels[x + 1] = current.G;
                            pixels[x + 2] = current.B;
                        }
                        pixels += bitmapData.Stride;
                    }
                }
            }
            finally
            {
                bitmap.UnlockBits(bitmapData);
            }
            return bitmap;
        }

        /// <summary>
        /// Convert map fileName to bitmap.
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static Bitmap Deconvert(string fileName)
        {
            Map map = Load(fileName);
            Bitmap bitmap = DeconvertBitmap(map, Color.White, Color.Black);
            return bitmap;
        }
    }
}
